﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.Logger;
using Cofe.Core.Property;
using Cofe.Core.Utils;
using Cofe.IO.Interfaces;

namespace Cofe.IO.Compress
{

    public class CompressMemoryStream : HookableMemoryStream
    {
        private bool _updating = false;

        public CompressMemoryStream(ICompressorWrapper wrapper, IPropertyHost rootPropertyHost, string filePath, FileAccess accessMode)
        {
            switch (accessMode)
            {
                case FileAccess.Read:
                case FileAccess.ReadWrite:
                    using (var sc = Task.Run<StreamContainer>(async () => await rootPropertyHost.OpenStreamAsync(true, false)).Result)
                    {
                        if (!(wrapper.ExtractOne(sc, filePath, null, this)))
                            throw new NotSupportedException();
                        this.IsModified = false;
                        this.Seek(0, SeekOrigin.Begin);
                    }
                    break;
            }

            //Hook the Closed function to write back changes to rootPropertyHost.
            switch (accessMode)
            {
                case FileAccess.ReadWrite:
                case FileAccess.Write:
                    this.OnClosing = (o, e) =>
                        {
                            try
                            {
                                if (!_updating && IsModified)
                                {
                                    _updating = true;

                                    this.Seek(0, SeekOrigin.Begin);

                                    using (var sc = rootPropertyHost.OpenStream(true, true))
                                        if (!(wrapper.CompressOne(sc, filePath, this)))
                                            throw new NotSupportedException();

                                    string rootPath = rootPropertyHost.Behaviors.GetProperty<string>(CofeProperties.FullParseName);
                                    string key, parsePath;
                                    PathFE.ParseFullParseName(rootPath, out key, out parsePath);
                                    parsePath = PathFE.Combine(rootPath, filePath);
                                    CofeServices.EventHub.DispatchEvent(this,
                                        CofeSystemEventArgs.FromParsePath(parsePath, false, ModifiedAction.Created));
                                    //CofeServices.EventHub.DispatchEvent(this,
                                    //    new CofeSystemEventArgs(key, ModifiedAction.Changed, false, rootPath));
                                }
                            }
                            finally
                            {
                                _updating = false;
                            }

                        };
                    break;
            }
        }
    }
}
